home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i025: cpp - a c preprocessor with some ANSI features, Part04/05
- Message-ID: <11033@xanth.cs.odu.edu>
- Date: 18 Jan 90 00:21:15 GMT
- Sender: tadguy@cs.odu.edu
- Reply-To: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
- Lines: 839
- Approved: tadguy@cs.odu.edu (Tad Guy)
-
- Submitted-by: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
- Posting-number: Volume 90, Issue 025
- Archive-name: unix/cpp/part04
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 4 (of 5)."
- # Contents: Cpp1.c
- # Wrapped by tadguy@xanth on Wed Jan 17 19:17:37 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Cpp1.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Cpp1.c'\"
- else
- echo shar: Extracting \"'Cpp1.c'\" \(26903 characters\)
- sed "s/^X//" >'Cpp1.c' <<'END_OF_FILE'
- X/*
- X * CPP main program.
- X *
- X * Edit history
- X * 21-May-84 MM "Field test" release
- X * 23-May-84 MM Some minor hacks.
- X * 30-May-84 ARF Didn't get enough memory for __DATE__
- X * Added code to read stdin if no input
- X * files are provided.
- X * 29-Jun-84 MM Added ARF's suggestions, Unixifying cpp.
- X * 11-Jul-84 MM "Official" first release (that's what I thought!)
- X * 22-Jul-84 MM/ARF/SCK Fixed line number bugs, added cpp recognition
- X * of #line, fixed problems with #include.
- X * 23-Jul-84 MM More (minor) include hacking, some documentation.
- X * Also, redid cpp's #include files
- X * 25-Jul-84 MM #line filename isn't used for #include searchlist
- X * #line format is <number> <optional name>
- X * 25-Jul-84 ARF/MM Various bugs, mostly serious. Removed homemade doprint
- X * 01-Aug-84 MM Fixed recursion bug, remove extra newlines and
- X * leading whitespace from cpp output.
- X * 02-Aug-84 MM Hacked (i.e. optimized) out blank lines and unneeded
- X * whitespace in general. Cleaned up unget()'s.
- X * 03-Aug-84 Keie Several bug fixes from Ed Keizer, Vrije Universitet.
- X * -- corrected arg. count in -D and pre-defined
- X * macros. Also, allow \n inside macro actual parameter
- X * lists.
- X * 06-Aug-84 MM If debugging, dump the preset vector at startup.
- X * 12-Aug-84 MM/SCK Some small changes from Sam Kendall
- X * 15-Aug-84 Keie/MM cerror, cwarn, etc. take a single string arg.
- X * cierror, etc. take a single int. arg.
- X * changed LINE_PREFIX slightly so it can be
- X * changed in the makefile.
- X * 31-Aug-84 MM USENET net.sources release.
- X * 7-Sep-84 SCH/ado Lint complaints
- X * 10-Sep-84 Keie Char's can't be signed in some implementations
- X * 11-Sep-84 ado Added -C flag, pathological line number fix
- X * 13-Sep-84 ado Added -E flag (does nothing) and "-" file for stdin.
- X * 14-Sep-84 MM Allow # 123 as a synonym for #line 123
- X * 19-Sep-84 MM scanid always reads to token, make sure #line is
- X * written to a new line, even if -C switch given.
- X * Also, cpp - - reads stdin, writes stdout.
- X * 03-Oct-84 ado/MM Several changes to line counting and keepcomments
- X * stuff. Also a rewritten control() hasher -- much
- X * simpler and no less "perfect". Note also changes
- X * in cpp3.c to fix numeric scanning.
- X * 04-Oct-84 MM Added recognition of macro formal parameters if
- X * they are the only thing in a string, per the
- X * draft standard.
- X * 08-Oct-84 MM One more attack on scannumber
- X * 15-Oct-84 MM/ado Added -N to disable predefined symbols. Fixed
- X * linecount if COMMENT_INVISIBLE enabled.
- X * 22-Oct-84 MM Don't evaluate the #if/#ifdef argument if
- X * compilation is supressed. This prevents
- X * unnecessary error messages in sequences such as
- X * #ifdef FOO -- undefined
- X * #if FOO == 10 -- shouldn't print warning
- X * 25-Oct-84 MM Fixed bug in false ifdef supression. On vms,
- X * #include <foo> should open foo.h -- this duplicates
- X * the behavior of Vax-C
- X * 31-Oct-84 ado/MM Parametized $ in indentifiers. Added a better
- X * token concatenator and took out the trial
- X * concatenation code. Also improved #ifdef code
- X * and cleaned up the macro recursion tester.
- X * 2-Nov-84 MM/ado Some bug fixes in token concatenation, also
- X * a variety of minor (uninteresting) hacks.
- X * 6-Nov-84 MM Happy Birthday. Broke into 4 files and added
- X * #if sizeof (basic_types)
- X * 9-Nov-84 MM Added -S* for pointer type sizes
- X * 13-Nov-84 MM Split cpp1.c, added vms defaulting
- X * 23-Nov-84 MM/ado -E supresses error exit, added CPP_INCLUDE,
- X * fixed strncpy bug.
- X * 3-Dec-84 ado/MM Added OLD_PREPROCESSOR
- X * 7-Dec-84 MM Stuff in Nov 12 Draft Standard
- X * 17-Dec-84 george Fixed problems with recursive macros
- X * 17-Dec-84 MM Yet another attack on #if's (f/t)level removed.
- X * 07-Jan-85 ado Init defines before doing command line options
- X * so -Uunix works.
- X * 21-Oct-85 RMS Rename `token' to `tokenbuf'.
- X * Allocate it dynamically, with size in `tokenbsize'.
- X * 23-Oct-85 RMS Do not print message about number of errors.
- X * 14-Mar-85 FNF Incorporate macro based C debugging package.
- X * Port to Commodore AMIGA.
- X * 20-Aug-88 Ois Changed format of documentation.
- X */
- X
- X/*)BUILD
- X $(PROGRAM) = cpp
- X $(FILES) = { cpp1 cpp2 cpp3 cpp4 cpp5 cpp6 }
- X $(INCLUDE) = { cppdef.h cpp.h }
- X $(STACK) = 2000
- X $(TKBOPTIONS) = {
- X STACK = 2000
- X }
- X*/
- X
- X#ifdef DOCUMENTATION
- X.TH CPP 1 "Amiga Programmer's Manual" "1st PDC distribution"
- X.SH NAME
- X.bo "cpp
- X- C Pre Processor. Macro-preprocess C programs.
- X.SH SYNOPSIS
- X.nf
- Xcpp [-options] [infile [outfile]]
- X.fi
- X.SH DESCRIPTION
- XCPP reads a C source file, expands macros and include files, and writes an
- Xinput file for the C compiler. If no file arguments are given, CPP reads
- Xfrom stdin and writes to stdout. If one file argument is given, it will
- Xdefine the input file, while two file arguments define both input and
- Xoutput files. The file name "-" is a synonym for stdin or stdout as
- Xappropriate.
- X
- XThe following options are supported. Options may be given in either case.
- X.in +5
- X.ta +0
- X.sp
- X.ti -5
- X-C@tIf set, source-file comments are written to the output file. This
- Xallows the output of CPP to be used as the input to a program, such as
- Xlint, that expects commands embedded in specially-formatted comments.
- X.sp
- X.ti -5
- X-Dname=value
- X.br
- XDefine the name as if the programmer wrote
- X
- X #define name value
- X
- Xat the start of the first file. If "=value" is not given, a value of "1"
- Xwill be used.
- X
- XOn non-unix and non-amiga systems, all alphabetic text will be forced to
- Xupper-case.
- X.sp
- X.ti -5
- X-E@tAlways return "success" to the operating system, even if errors were
- Xdetected. Note that some fatal errors, such as a missing #include file,
- Xwill terminate CPP, returning "failure" even if the -E option is given.
- X.sp
- X.ti -5
- X-Idirectory
- X.br
- XAdd this directory to the list of directories searched for #include "..."
- Xand #include <...> commands. Note that there is no space between the "-I"
- Xand the directory string. More than one -I command is permitted. On
- Xnon-Unix systems "directory" is forced to upper-case.
- X.sp
- X.ti -5
- X-N@tCPP normally predefines some symbols defining the target computer and
- Xoperating system. If -N is specified, no symbols will be predefined. If
- X-N -N is specified, the "always present" symbols, __LINE__, __FILE__,
- X__TIME__ and __DATE__ are not defined.
- X.sp
- X.ti -5
- X-Stext
- X.br
- XCPP normally assumes that the size of the target computer's basic variable
- Xtypes is the same as the size of these types of the host computer. (This
- Xcan be overridden when CPP is compiled, however.) The -S option allows
- Xdynamic respecification of these values. "text" is a string of numbers,
- Xseparated by commas, that specifies correct sizes. The sizes must be
- Xspecified in the exact order:
- X
- X char short int long float double
- X
- XIf you specify the option as "-S*text", pointers to these types will be
- Xspecified. -S* takes one additional argument for pointer to function (e.g.
- Xint (*)())
- X
- XFor example, to specify sizes appropriate for a PDP-11, you would write:
- X
- X c s i l f d func
- X -S1,2,2,2,4,8,
- X -S*2,2,2,2,2,2,2
- X
- XNote that all values must be specified.
- X.br;.it -1
- XNote also that this is not allowed by the 11-Jan-88 Draft, and therefore
- Xhas made into an option when compiling Cpp.
- X.it 0
- X.sp
- X.ti -5
- X-Uname
- X.br
- XUndefine the name as if
- X
- X #undef name
- X
- Xwere given. On non-Unix systems, "name" will be forced to upper-case.
- X.sp
- X.ti -5
- X-Xnumber
- X.br
- XEnable debugging code. If no value is given, a value of 1 will be used.
- X(For maintenence of CPP only.)
- X.in -5
- X.SH Pre-Defined Variables
- XWhen CPP begins processing, the following variables will have been defined
- X(unless the -N option is specified):
- X.sp
- XTarget computer (as appropriate):
- X.sp
- X pdp11, vax, M68000 m68000 m68k, amiga
- X.sp
- XTarget operating system (as appropriate):
- X.sp
- X rsx, rt11, vms, unix, amigados
- X.sp
- XTarget compiler (as appropriate):
- X.sp
- X decus, vax11c, pdc PDC __PDC__
- X.sp
- XThe implementor may add definitions to this list. The default definitions
- Xmatch the definition of the host computer, operating system, and C
- Xcompiler.
- X.sp
- XThe following are always available unless undefined (or -N was specified
- Xtwice):
- X
- X.in +16
- X.ta
- X.ta +0
- X.ti -12
- X__FILE__@tThe input (or #include) file being compiled (as a quoted string).
- X.ti -12
- X__LINE__@tThe line number being compiled.
- X.ti -12
- X__DATE__@tThe date of compilation as a quoted string of the format
- X"Mmm dd yyyy".
- X.ti -12
- X__TIME__@tThe time of the start of compilation as a quoted string of the
- Xformat "hh:mm:ss". Thus,
- X.br
- X printf("Bug at line %s,", __LINE__);
- X printf(" source file %s", __FILE__);
- X printf("@ compiled@ on@ %s@ %s", __DATE__, __TIME__);
- X.br
- X.in -16
- X.SH Supported directives
- X.br; #assert <expression>
- X.br; #define <token> <replacement>
- X.br; #elif <expression>
- X.br; #else <expression>
- X.br; #endif
- X.br; #error
- X.br; #if <expression>
- X.br; #ifdef <token>
- X.br; #ifndef <token>
- X.br; #include <filename>
- X.br; #line <number> <filename>
- X.br; #pragma <anything>
- X.br; #undef <token>
- X.br; #debug
- X.br; #nodebug
- X.sp
- XUnsupported # commands are copied verbatim into the output, so that maybe
- Xthe compiler knows what to do with them.
- X.SH Draft Proposed Ansi Standard Considerations
- XThe current version of the Draft Proposed Standard explicitly states that
- X"readers are requested not to specify or claim conformance to this draft."
- XReaders and users of Decus CPP should not assume that Decus CPP conforms to
- Xthe standard, or that it will conform to the actual C Language Standard.
- X
- XWhen CPP is itself compiled, many features of the Draft Proposed Standard
- Xthat are incompatible with existing preprocessors may be disabled. See the
- Xcomments in CPP's source for details.
- X
- XThe latest version of the Draft Proposed Standard (as reflected in Decus
- XCPP) is dated November 12, 1984, and bits from K&R V2 are put in by Ois.
- X
- XComments are removed from the input text. The comment is replaced by a
- Xsingle space character. The -C option preserves comments, writing them to
- Xthe output file.
- X
- XThe '$' character is considered to be a letter. This is a permitted
- Xextension.
- X
- XThe following new features of C are processed by CPP:
- X.sp
- X.* The following .br commands are there so the preprocessor
- X.* does not get confused when compiling cpp1.c
- X.nf
- X.br; #if, #elif
- X.br; #elif expression (#else #if)
- X.br; '\xNNN' (Hexadecimal constant)
- X.br; '\a' (Ascii BELL)
- X.br; '\v' (Ascii Vertical Tab)
- X.br; #if defined NAME 1 if defined, 0 if not
- X.br; #if defined (NAME) 1 if defined, 0 if not
- X.br; #if sizeof (basic type)
- X.br; #error Generates error message
- X.br; unary +
- X.br; 123U, 123LU Unsigned ints and longs.
- X.br; 12.3L Long double numbers
- X.br; token##token Token concatenation in macros
- X.br; #macro-formal String generation in macros
- X.br; #include token Expands to filename
- X.fi
- X
- XThe Draft Proposed Standard has extended C, adding a constant string
- Xconcatenation operator, where
- X
- X "foo" "bar"
- X
- Xis regarded as the single string "foobar". (This does not affect CPP's
- Xprocessing but does permit a limited form of macro argument substitution
- Xinto strings as will be discussed.)
- X
- XThe Standard Committee plans to add token concatenation to #define command
- Xlines. One suggested implementation is as follows: the sequence
- X"Token1 ## Token2" is treated as if the programmer wrote "Token1Token2".
- X
- XThis could be used as follows:
- X
- X #line 123
- X #define ATLINE foo ## __LINE__
- X
- XATLINE would be defined as foo123.
- X
- XNote that "Token1" and "Token2" both must be valid tokens, but the
- Xconcatenation of their expanded forms may not be a _single_ valid token. In
- Xthat case, K&R state that the behaviour is undefined. So if you wish to
- Xmake portable use of this facility, do not do the following:
- X
- X #define cat(x, y) x ## y
- X cat(foo, 1.23)
- X
- Xwhich will produce
- X
- X foo1.23
- X
- Xand that is not a single token.
- X
- XIf the tokens T1 and T2 are concatenated into T3, this implementation
- Xoperates as follows:
- X
- X 1.@ Expand T1 if it is a macro.
- X 2.@ Expand T2 if it is a macro.
- X 3.@ Join the tokens, forming T3.
- X 4.@ Rescan T3, looking for tokens, that may be expanded again.
- X
- X A macro formal parameter will be substituted into a string or
- Xcharacter constant if it is the only component of that constant:
- X
- X #define VECSIZE 123
- X #define vprint(name, size) \
- X printf("name" "[" "size" "] = {\n")
- X ... vprint(vector, VECSIZE);
- X
- Xexpands (effectively) to
- X
- X vprint("vector[123] = {\n");
- X
- XNote that this will be useful if your C compiler supports the new string
- Xconcatenation operation noted above. As implemented here, if you write
- X
- X #define string(arg) "arg"
- X ... string("foo") ...
- X
- XThis implementation generates "foo", rather than the strictly correct
- X""foo"" (which will probably generate an error message). This is, strictly
- Xspeaking, an error in CPP and may be removed from future releases.
- X.it -1
- XNote that the above feature of replacing macro formals inside quotes is
- Xnon-standard. The Committee thought the following to be better:
- X.it 0
- X.sp
- XIf a macro formal argument is immediately preceeded by a #, the argument
- Xsupplied when expanding the macro will be surrounded by double quotes, and
- Xeach double quote or backslash will be preceeded by a backslash. An example
- Xof this would be:
- X
- X #define string(arg) #arg
- X ... string(foo) ...
- X
- Xwhich produces "foo". Note that this feature is useless if you want your
- Xstring to contain an odd number of quotes:
- X
- X string(Hello");
- X
- Xwill produce an error message, complaining about unterminated strings.
- X
- X.SH Error messages
- XMany. CPP prints warning or error messages if you try to use multiple-byte
- Xcharacter constants (non-transportable) if you #undef a symbol that was not
- Xdefined, or if your program has potentially nested comments.
- X.SH Author
- XMartin Minow, minor changes by RMS, FNF, OIS.
- X.SH Bugs
- XThe #if expression processor uses signed integers only.
- XI.e, #if 0xFFFFu < 0 may be TRUE.
- X#endif /* DOCUMENTATION */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "cppdef.h"
- X#include "cpp.h"
- X
- X/*
- X * Commonly used global variables:
- X * line is the current input line number.
- X * wrongline is set in many places when the actual output
- X * line is out of sync with the numbering, e.g,
- X * when expanding a macro with an embedded newline.
- X *
- X * tokenbuf holds the last identifier scanned (which might
- X * be a candidate for macro expansion).
- X * errors is the running cpp error counter.
- X * infile is the head of a linked list of input files (extended by
- X * #include and macros being expanded). infile always points
- X * to the current file/macro. infile->parent to the includer,
- X * etc. infile->fd is NULL if this input stream is a macro.
- X */
- Xint line; /* Current line number */
- Xint wrongline; /* Force #line to compiler */
- Xchar *tokenbuf; /* Buffer for current input token */
- Xint tokenbsize; /* Allocated size of tokenbuf, */
- X /* not counting zero at end. */
- Xint errors; /* cpp error counter */
- XFILEINFO *infile = NULL; /* Current input file */
- X#if DEBUG
- Xint debug; /* TRUE if debugging now */
- X#endif
- X/*
- X * This counter is incremented when a macro expansion is initiated.
- X * If it exceeds a built-in value, the expansion stops -- this tests
- X * for a runaway condition:
- X * #define X Y
- X * #define Y X
- X * X
- X * This can be disabled by falsifying rec_recover. (Nothing does this
- X * currently: it is a hook for an eventual invocation flag.)
- X */
- Xint recursion; /* Infinite recursion counter */
- Xint rec_recover = TRUE; /* Unwind recursive macros */
- X
- X/*
- X * instring is set TRUE when a string is scanned. It modifies the
- X * behavior of the "get next character" routine, causing all characters
- X * to be passed to the caller (except <DEF_MAGIC>). Note especially that
- X * comments and \<newline> are not removed from the source. (This
- X * prevents cpp output lines from being arbitrarily long).
- X *
- X * inmacro is set by #define -- it absorbs comments and converts
- X * form-feed and vertical-tab to space, but returns \<newline>
- X * to the caller. Strictly speaking, this is a bug as \<newline>
- X * shouldn't delimit tokens, but we'll worry about that some other
- X * time -- it is more important to prevent infinitly long output lines.
- X *
- X * instring and inmarcor are parameters to the get() routine which
- X * were made global for speed.
- X */
- Xint instring = FALSE; /* TRUE if scanning string */
- Xint inmacro = FALSE; /* TRUE if #defining a macro */
- X
- X/*
- X * work[] and workp are used to store one piece of text in a temporay
- X * buffer. To initialize storage, set workp = work. To store one
- X * character, call save(c); (This will fatally exit if there isn't
- X * room.) To terminate the string, call save(EOS). Note that
- X * the work buffer is used by several subroutines -- be sure your
- X * data won't be overwritten. The extra byte in the allocation is
- X * needed for string formal replacement.
- X */
- Xchar work[NWORK + 1]; /* Work buffer */
- Xchar *workp; /* Work buffer pointer */
- X
- X/*
- X * keepcomments is set TRUE by the -C option. If TRUE, comments
- X * are written directly to the output stream. This is needed if
- X * the output from cpp is to be passed to lint (which uses commands
- X * embedded in comments). cflag contains the permanent state of the
- X * -C flag. keepcomments is always falsified when processing #control
- X * commands and when compilation is supressed by a false #if
- X *
- X * If eflag is set, CPP returns "success" even if non-fatal errors
- X * were detected.
- X *
- X * If nflag is non-zero, no symbols are predefined except __LINE__.
- X * __FILE__, and __DATE__. If nflag > 1, absolutely no symbols
- X * are predefined.
- X */
- Xint keepcomments = FALSE; /* Write out comments flag */
- Xint cflag = FALSE; /* -C option (keep comments) */
- Xint eflag = FALSE; /* -E option (never fail) */
- Xint nflag = 0; /* -N option (no predefines) */
- Xint wflag = FALSE; /* -W option (write #defines) */
- X
- X/*
- X * ifstack[] holds information about nested #if's. It is always
- X * accessed via *ifptr. The information is as follows:
- X * WAS_COMPILING state of compiling flag at outer level.
- X * ELSE_SEEN set TRUE when #else seen to prevent 2nd #else.
- X * TRUE_SEEN set TRUE when #if or #elif succeeds
- X * ifstack[0] holds the compiling flag. It is TRUE if compilation
- X * is currently enabled. Note that this must be initialized TRUE.
- X */
- Xchar ifstack[BLK_NEST] = { TRUE }; /* #if information */
- Xchar *ifptr = ifstack; /* -> current ifstack[] */
- X
- X/*
- X * incdir[] stores the -i directories (and the system-specific
- X * #include <...> directories.
- X */
- Xchar *incdir[NINCLUDE]; /* -i directories */
- Xchar **incend = incdir; /* -> free space in incdir[] */
- X
- X/*
- X * This is the table used to predefine target machine and operating
- X * system designators. It may need hacking for specific circumstances.
- X * Note: it is not clear that this is part of the Ansi Standard.
- X * The -N option supresses preset definitions.
- X */
- Xchar *preset[] = { /* names defined at cpp start */
- X#ifdef MACHINE
- X MACHINE,
- X#endif
- X#ifdef SYSTEM
- X SYSTEM,
- X#endif
- X#ifdef COMPILER
- X COMPILER,
- X#endif
- X#if DEBUG
- X "decus_cpp", /* Ourselves! */
- X#endif
- X NULL /* Must be last */
- X};
- X
- X/*
- X * The value of these predefined symbols must be recomputed whenever
- X * they are evaluated. The order must not be changed.
- X */
- Xchar *magic[] = { /* Note: order is important */
- X "__LINE__",
- X "__FILE__",
- X NULL /* Must be last */
- X};
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X register int i;
- X extern FILE *freopen ();
- X
- X DBUG_ENTER ("main");
- X DBUG_PUSH ("d:t");
- X#if HOST == SYS_VMS
- X argc = getredirection(argc, argv); /* vms >file and <file */
- X#endif
- X initdefines(); /* O.S. specific def's */
- X i = dooptions(argc, argv); /* Command line -flags */
- X switch (i) {
- X case 3:
- X /*
- X * Get output file, "-" means use stdout.
- X */
- X if (!streq(argv[2], "-")) {
- X#if HOST == SYS_VMS
- X /*
- X * On vms, reopen stdout with "vanilla rms" attributes.
- X */
- X if ((i = creat(argv[2], 0, "rat=cr", "rfm=var")) == -1
- X || dup2(i, fileno(stdout)) == -1) {
- X#else
- X if (freopen(argv[2], "w", stdout) == NULL) {
- X#endif
- X perror(argv[2]);
- X cerror("Can't open output file \"%s\"", argv[2]);
- X exit(IO_ERROR);
- X }
- X } /* Continue by opening input */
- X case 2: /* One file -> stdin */
- X /*
- X * Open input file, "-" means use stdin.
- X */
- X if (!streq(argv[1], "-")) {
- X if (freopen(argv[1], "r", stdin) == NULL) {
- X perror(argv[1]);
- X cerror("Can't open input file \"%s\"", argv[1]);
- X exit(IO_ERROR);
- X }
- X strcpy(work, argv[1]); /* Remember input filename */
- X break;
- X } /* Else, just get stdin */
- X case 0: /* No args? */
- X case 1: /* No files, stdin -> stdout */
- X#if HOST == SYS_UNIX || HOST == SYS_AMIGADOS
- X work[0] = EOS; /* Unix can't find stdin name */
- X#else
- X fgetname(stdin, work); /* Vax-11C, Decus C know name */
- X#endif
- X break;
- X
- X default:
- X exit(IO_ERROR); /* Can't happen */
- X }
- X setincdirs(); /* Setup -I include directories */
- X addfile(stdin, work); /* "open" main input file */
- X#if DEBUG
- X if (debug > 0)
- X dumpdef("preset #define symbols");
- X#endif
- X cppmain(); /* Process main file */
- X if ((i = (ifptr - &ifstack[0])) != 0) {
- X#if OLD_PREPROCESSOR
- X ciwarn("Inside #ifdef block at end of input, depth = %d", i);
- X#else
- X cierror("Inside #ifdef block at end of input, depth = %d", i);
- X#endif
- X }
- X fflush(stdout);
- X fclose(stdout);
- X if (errors > 0 && !eflag)
- X DBUG_RETURN(IO_ERROR);
- X DBUG_RETURN(IO_NORMAL); /* No errors or -E option set */
- X}
- X
- XFILE_LOCAL
- Xcppmain()
- X/*
- X * Main process for cpp -- copies tokens from the current input
- X * stream (main file, include file, or a macro) to the output
- X * file.
- X */
- X{
- X register int c; /* Current character */
- X register int counter; /* newlines and spaces */
- X extern int output(); /* Output one character */
- X
- X DBUG_ENTER ("cppmain");
- X /* Initialize for reading tokens */
- X tokenbsize = 50;
- X tokenbuf = getmem (tokenbsize + 1);
- X
- X /*
- X * Explicitly output a #line at the start of cpp output so
- X * that lint (etc.) knows the name of the original source
- X * file. If we don't do this explicitly, we may get
- X * the name of the first #include file instead.
- X */
- X sharp();
- X /*
- X * This loop is started "from the top" at the beginning of each line
- X * wrongline is set TRUE in many places if it is necessary to write
- X * a #line record. (But we don't write them when expanding macros.)
- X *
- X * The counter variable has two different uses: at
- X * the start of a line, it counts the number of blank lines that
- X * have been skipped over. These are then either output via
- X * #line records or by outputting explicit blank lines.
- X * When expanding tokens within a line, the counter remembers
- X * whether a blank/tab has been output. These are dropped
- X * at the end of the line, and replaced by a single blank
- X * within lines.
- X */
- X for (;;) {
- X counter = 0; /* Count empty lines */
- X for (;;) { /* For each line, ... */
- X while (type[(c = get())] == SPA) /* Skip leading blanks */
- X ; /* in this line. */
- X if (c == '\n') /* If line's all blank, */
- X ++counter; /* Do nothing now */
- X else if (c == '#') { /* Is 1st non-space '#' */
- X keepcomments = FALSE; /* Don't pass comments */
- X counter = control(counter); /* Yes, do a #command */
- X keepcomments = (cflag && compiling);
- X }
- X else if (c == EOF_CHAR) /* At end of file? */
- X break;
- X else if (!compiling) { /* #ifdef false? */
- X skipnl(); /* Skip to newline */
- X counter++; /* Count it, too. */
- X }
- X else {
- X break; /* Actual token */
- X }
- X }
- X if (c == EOF_CHAR) /* Exit process at */
- X break; /* End of file */
- X /*
- X * If the loop didn't terminate because of end of file, we
- X * know there is a token to compile. First, clean up after
- X * absorbing newlines. counter has the number we skipped.
- X */
- X if ((wrongline && infile->fp != NULL) || counter > 4)
- X sharp(); /* Output # line number */
- X else { /* If just a few, stuff */
- X while (--counter >= 0) /* them out ourselves */
- X putchar('\n');
- X }
- X /*
- X * Process each token on this line.
- X */
- X unget(); /* Reread the char. */
- X for (;;) { /* For the whole line, */
- X do { /* Token concat. loop */
- X for (counter = 0; (type[(c = get())] == SPA);) {
- X#if COMMENT_INVISIBLE
- X if (c != COM_SEP)
- X counter++;
- X#else
- X counter++; /* Skip over blanks */
- X#endif
- X }
- X if (c == EOF_CHAR || c == '\n')
- X goto end_line; /* Exit line loop */
- X else if (counter > 0) /* If we got any spaces */
- X putchar(' '); /* Output one space */
- X c = macroid(c); /* Grab the token */
- X } while (type[c] == LET && catenate());
- X if (c == EOF_CHAR || c == '\n') /* From macro exp error */
- X goto end_line; /* Exit line loop */
- X switch (type[c]) {
- X case LET:
- X fputs(tokenbuf, stdout); /* Quite ordinary token */
- X break;
- X
- X
- X case DIG: /* Output a number */
- X case DOT: /* Dot may begin floats */
- X scannumber(c, output);
- X break;
- X
- X case QUO: /* char or string const */
- X scanstring(c, output); /* Copy it to output */
- X break;
- X
- X default: /* Some other character */
- X cput(c); /* Just output it */
- X break;
- X } /* Switch ends */
- X } /* Line for loop */
- Xend_line: if (c == '\n') { /* Compiling at EOL? */
- X putchar('\n'); /* Output newline, if */
- X if (infile->fp == NULL) /* Expanding a macro, */
- X wrongline = TRUE; /* Output # line later */
- X }
- X } /* Continue until EOF */
- X if (wflag)
- X outdefines(); /* Write out #defines */
- X DBUG_VOID_RETURN;
- X}
- X
- Xoutput(c)
- Xint c;
- X/*
- X * Output one character to stdout -- output() is passed as an
- X * argument to scanstring()
- X */
- X{
- X#if COMMENT_INVISIBLE
- X if (c != TOK_SEP && c != COM_SEP)
- X#else
- X if (c != TOK_SEP)
- X#endif
- X putchar(c);
- X}
- X
- Xstatic char *sharpfilename = NULL;
- X
- XFILE_LOCAL
- Xsharp()
- X/*
- X * Output a line number line.
- X */
- X{
- X register char *name;
- X
- X DBUG_ENTER ("sharp");
- X if (keepcomments) /* Make sure # comes on */
- X putchar('\n'); /* a fresh, new line. */
- X printf("#%s %d", LINE_PREFIX, line);
- X if (infile->fp != NULL) {
- X name = (infile->progname != NULL)
- X ? infile->progname : infile->filename;
- X if (sharpfilename == NULL
- X || sharpfilename != NULL && !streq(name, sharpfilename)) {
- X if (sharpfilename != NULL)
- X free(sharpfilename);
- X sharpfilename = savestring(name);
- X printf(" \"%s\"", name);
- X }
- X }
- X putchar('\n');
- X wrongline = FALSE;
- X DBUG_VOID_RETURN;
- X}
- END_OF_FILE
- if test 26903 -ne `wc -c <'Cpp1.c'`; then
- echo shar: \"'Cpp1.c'\" unpacked with wrong size!
- fi
- # end of 'Cpp1.c'
- fi
- echo shar: End of archive 4 \(of 5\).
- cp /dev/null ark4isdone
- MISSING=""
- for I in 1 2 3 4 5 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 5 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
- amiga@cs.odu.edu
- or amiga@xanth.cs.odu.edu ( obsolescent mailers may need this address )
- or ...!uunet!xanth!amiga ( very obsolescent mailers need this address )
-
- Comments, questions, and suggestions s should be addressed to ``amiga-request''
- (only use ``amiga'' for submissions) at the above addresses.
-